home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 April / macformat-049.iso / mac / Shareware Plus / Developers / Mercutio MDEF v1.3.3 / Sample Codeƒ / PopupDialog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-26  |  13.5 KB  |  489 lines  |  [TEXT/CWIE]

  1.  
  2. #include <Types.h>
  3. #include <Dialogs.h>
  4. #include <Errors.h>
  5. #include <Menus.h>
  6. #include <Memory.h>
  7. #include <Controls.h>
  8. #include <Quickdraw.h>
  9. #include <Resources.h>
  10. #include <ToolUtils.h>
  11. #include <LowMem.h>
  12. #include <QuickDrawText.h>
  13. #include <OSUtils.h>
  14. #include <Events.h>
  15. #include <Windows.h>
  16. #include <Fonts.h>
  17.  
  18. #include "MercutioAPI.h"
  19. #include "PopupDialog.h"
  20.  
  21. #define        popupDLOGID    3001
  22. #define        popup1Item    3
  23. #define        popup2Item    7
  24. #define        defaultItem    5
  25.  
  26. #define        enterKey    3
  27. #define        helpKey        5
  28. #define        deleteKey    8
  29. #define        tabKey        9
  30. #define        linefeedKey    10
  31. #define        cr            13
  32.  
  33. #define        Off     0
  34. #define        On     1
  35.  
  36. #define        periodKey    46
  37. #define        slashKey    47
  38. #define        questionmarkKey    63
  39.  
  40. /* Define HiWrd and LoWrd macros for efficiency. */
  41. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  42. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  43.  
  44. /* Define TopLeft and BotRight macros for convenience. Notice the implicit
  45.    dependency on the ordering of fields within a Rect */
  46. #define TopLeft(aRect)    (* (Point *) &(aRect).top)
  47. #define BotRight(aRect)    (* (Point *) &(aRect).bottom)
  48.  
  49.  
  50. enum    {
  51.     normalPopupID = 11,
  52.     smallPopupID
  53.     };
  54.  
  55. typedef struct {
  56.         MenuHandle    hMenu;
  57.         short    selectedItem;
  58.         Boolean    smallFont;
  59.     } PopupInfo, *PopupInfoPtr;
  60.  
  61. typedef struct {
  62.         PopupInfo    normalPopupMenu;
  63.         PopupInfo    smallPopupMenu;
  64.     } DialogGlobals, *DialogGlobalsPtr;
  65.  
  66. long PopUpSelect (MenuHandle theMenu, Point popPt, short popupItem, Boolean useWFont);
  67.  
  68. PopupInfoPtr ItemToMenuInfo (DialogPtr theDialog, short item);
  69. PopupInfoPtr ItemToMenuInfo (DialogPtr theDialog, short item) {
  70.     DialogGlobalsPtr    theGlobals;
  71.  
  72.     theGlobals = (DialogGlobalsPtr)GetWRefCon(theDialog);
  73.     if (item == popup1Item) {
  74.         return (&theGlobals->normalPopupMenu);
  75.     } else {
  76.         return (&theGlobals->smallPopupMenu);
  77.     }
  78. }
  79.  
  80.  
  81. pascal void FakeClick (DialogPtr theDialog, short theButton);
  82. pascal void FakeClick (DialogPtr theDialog, short theButton) {
  83.     GrafPtr     port;
  84.  
  85.     short    iType;
  86.     Handle    iHandle;
  87.     Rect    iRect;
  88.     long    finalTicks;
  89.  
  90.     GetPort(&port);                                        /* save old port */
  91.     SetPort(theDialog);                                        /* make dialog port */
  92.  
  93.     GetDialogItem(theDialog, theButton, &iType, &iHandle, &iRect);
  94.     HiliteControl((ControlHandle)iHandle, On);
  95.     Delay(8, &finalTicks);
  96.     HiliteControl((ControlHandle)iHandle, Off);
  97.     SetPort(port);                                        /* restore old port */
  98. }
  99.  
  100.  
  101. pascal void DrawDefaultButton (DialogPtr theDialog, short theButton);
  102. pascal void DrawDefaultButton (DialogPtr theDialog, short theButton) {
  103.     GrafPtr     port;
  104.  
  105.     short    iType;
  106.     Handle    iHandle;
  107.     Rect    iRect;
  108.     PenState    ps;
  109.  
  110.     GetPort(&port);                                        /* save old port */
  111.     SetPort(theDialog);                                        /* make dialog port */
  112.     GetDialogItem(theDialog, theButton, &iType, &iHandle, &iRect);
  113.     GetPenState(&ps);
  114.     
  115.     PenNormal();
  116.     PenSize(3,3);
  117.     InsetRect(&iRect, -4, -4);
  118.     FrameRoundRect(&iRect, 16, 16);
  119.     SetPenState(&ps);
  120.     
  121.     SetPort(port);                                        /* restore old port */
  122. }
  123.  
  124.  
  125.  
  126.  
  127. pascal void UpdatePopUp (DialogPtr theDialog, short item);
  128. pascal void UpdatePopUp (DialogPtr theDialog, short item) {
  129.     GrafPtr     port;
  130.     short    iType;
  131.     Handle    iHandle;
  132.     Rect    iRect;
  133.     PopupInfoPtr    mInfo;
  134.     
  135.     GetPort(&port);                                        /* save old port */
  136.     SetPort(theDialog);                                        /* make dialog port */
  137.  
  138.     mInfo = ItemToMenuInfo(theDialog, item);
  139.     GetDialogItem(theDialog, item, &iType, &iHandle, &iRect);
  140.     
  141.     InsetRect(&iRect, -2, -2);
  142.     EraseRect(&iRect);
  143.     InsetRect(&iRect, 2, 2);
  144.     
  145.     if (mInfo->smallFont) {
  146.         TextSize(9);
  147.         TextFont(geneva);
  148.     }
  149.     MDEF_CalcItemSize(mInfo->hMenu, mInfo->selectedItem, &iRect);
  150.     MoveTo(iRect.left + 2, iRect.bottom);
  151.     LineTo(iRect.right, iRect.bottom);
  152.     MoveTo(iRect.right, iRect.top + 2);
  153.     LineTo(iRect.right, iRect.bottom);
  154.  
  155.     MoveTo(iRect.left + 6, iRect.bottom - 5);    // move to text position 
  156.     FillRect(&iRect, &qd.white);
  157.  
  158.     MDEF_DrawItem(mInfo->hMenu, mInfo->selectedItem, iRect);
  159.  
  160.     FrameRect(&iRect);
  161.     SetDialogItem(theDialog, item, iType, iHandle, &iRect);
  162.  
  163.     if (mInfo->smallFont) {
  164.         TextSize(0);
  165.         TextFont(0);
  166.     }
  167.     SetPort(port);                                        /* restore old port */
  168. }
  169.  
  170.  
  171.  
  172.  
  173. void HandleMouseDown (DialogPtr theDialog, short itemHit);
  174. void HandleMouseDown (DialogPtr theDialog, short itemHit) {
  175.     GrafPtr     port;
  176.     short    iType;
  177.     Handle    iHandle;
  178.     Rect    iRect;
  179.     PopupInfoPtr    mInfo;
  180.     Rect    popupRect;
  181.     long    popupResult;
  182.  
  183.     GetPort(&port);                                        /* save old port */
  184.     SetPort(theDialog);                                        /* make dialog port */
  185.  
  186.      if ((itemHit == popup1Item) | (itemHit == popup2Item)) {
  187.         mInfo = ItemToMenuInfo(theDialog, itemHit);
  188.         GetDialogItem(theDialog, itemHit, &iType, &iHandle, &iRect);
  189.         SetRect(&popupRect, iRect.left, iRect.top, iRect.left + (**(mInfo->hMenu)).menuWidth + 4, iRect.bottom + 2);
  190.         LocalToGlobal(&TopLeft(popupRect));
  191.         LocalToGlobal(&BotRight(popupRect));
  192.         InsetRect(&popupRect, 1, 1);
  193.         
  194.         if (mInfo->smallFont) {
  195.             TextSize(9);
  196.             TextFont(geneva);
  197.         }
  198.     
  199.         popupResult = PopUpSelect(mInfo->hMenu, TopLeft(popupRect), mInfo->selectedItem, mInfo->smallFont);
  200.         
  201.         if (mInfo->smallFont) {
  202.             TextSize(0);
  203.             TextFont(0);
  204.         }
  205.         
  206.         if ((popupResult > 0) && (LoWrd(popupResult) != mInfo->selectedItem)) {
  207.             CheckItem(mInfo->hMenu, mInfo->selectedItem, FALSE);
  208.             mInfo->selectedItem = LoWrd(popupResult);
  209.             UpdatePopUp(theDialog, itemHit);
  210.         }
  211.      }
  212.     SetPort(port);                                        /* restore old port */
  213. }
  214.  
  215.  
  216.  
  217. void HandleEvents (DialogPtr theDialog);
  218. void HandleEvents (DialogPtr theDialog) {
  219.     DialogGlobalsPtr    theGlobals;
  220.     Boolean    done;
  221.     Boolean    eventOccured;
  222.     short    itemHit;
  223.     EventRecord    theEvent;
  224.     short    theKey;
  225.     WindowPtr    whichWindow;
  226.     short    windowLoc;
  227.     long    matchedItem;
  228.     short    menuNum;
  229.     short    itemNum;
  230.     
  231.     theGlobals = (DialogGlobalsPtr)GetWRefCon(theDialog);
  232.     done = FALSE;
  233.     
  234.     while (!done) {
  235.         eventOccured = GetNextEvent(everyEvent, &theEvent);
  236.         if (eventOccured) {
  237.             if (IsDialogEvent(&theEvent)) {
  238.                 if (DialogSelect(&theEvent, &whichWindow, &itemHit)) {
  239.                     HandleMouseDown((DialogPtr)whichWindow, itemHit);
  240.                 }
  241.             }
  242.             switch (theEvent.what) {
  243.                 case keyDown:
  244.                 case autoKey:                       /* check for menukey equivalents */
  245.                     theKey = theEvent.message & charCodeMask;
  246.                     if (theKey == cr) {
  247.                         itemHit = ok;
  248.                         FakeClick(theDialog, itemHit);
  249.                     } else if ((theEvent.modifiers & cmdKey) && (theKey == periodKey)) {    /* Command key down */
  250.                         itemHit = cancel;
  251.                         FakeClick(theDialog, itemHit);
  252.                     } else {
  253.                         matchedItem = MDEF_MenuKey(theEvent.message, theEvent.modifiers, theGlobals->normalPopupMenu.hMenu);
  254.                         if (matchedItem > 0) { 
  255.                             menuNum = HiWord(matchedItem);
  256.                             itemNum = LoWord(matchedItem);
  257.                             if (menuNum == normalPopupID) {
  258.                                 theGlobals->normalPopupMenu.selectedItem = itemNum;
  259.                                 UpdatePopUp(theDialog, popup1Item);
  260.                             } else if (menuNum == smallPopupID) {
  261.                                 theGlobals->smallPopupMenu.selectedItem = itemNum;
  262.                                 UpdatePopUp(theDialog, popup2Item);
  263.                             }
  264.                         }
  265.                     }
  266.                     break;
  267.                     
  268.             case mouseDown:
  269.                 windowLoc = FindWindow(theEvent.where, &whichWindow);
  270.                 switch ( windowLoc ) {
  271.                     case inMenuBar:  
  272.                         SysBeep(1);
  273.                         break;
  274.                     case inSysWindow:           /* let the system handle the mouseDown */
  275.                         SystemClick(&theEvent, whichWindow);
  276.                         break;
  277.                     case inContent:
  278.                         if ( whichWindow != FrontWindow() ) {
  279.                             SelectWindow(whichWindow);
  280.                             /*DoEvent(event);*/    /* use this line for "do first click" */
  281.                         }
  282.                         break;
  283.                     case inDrag:                /* pass screenBits.bounds to get all gDevices */
  284.                         DragWindow(whichWindow, theEvent.where, &qd.screenBits.bounds);
  285.                         break;
  286.                     case inGoAway:
  287.                         if ( TrackGoAway(whichWindow, theEvent.where) )
  288.                             // DoCloseWindow(whichWindow); /* we donUt care if the user cancelled */
  289.                         break;
  290.                     case inGrow:
  291.                         // DoGrowWindow(whichWindow, theEvent);
  292.                         break;
  293.                     case inZoomIn:
  294.                     case inZoomOut:
  295.                     if ( TrackBox(whichWindow, theEvent.where, windowLoc) )
  296.                             // DoZoomWindow(whichWindow, windowLoc);
  297.                         break;
  298.                 }
  299.                 break;
  300.             default:
  301.                 DialogSelect(&theEvent, &whichWindow, &itemHit);
  302.                 break;
  303.             }
  304.         }
  305.         done = ((itemHit == ok) || (itemHit == cancel));
  306.     }
  307. }
  308.  
  309.  
  310.  
  311. void doPopupDialog () {
  312.     DialogPtr    theDialog;
  313.     short    iType;
  314.     Handle    iHandle;
  315.     Rect    iRect;
  316.     DialogGlobals    theGlobals;
  317.     
  318.     theDialog = GetNewDialog(popupDLOGID, NULL, (WindowPtr) -1L);
  319.     if (theDialog == 0L) {
  320.         SysBeep(1);
  321.     } else {
  322.         SetPort(theDialog);
  323.         SetWRefCon(theDialog, (long)&theGlobals);
  324.         
  325.         theGlobals.normalPopupMenu.hMenu = GetMenu(normalPopupID);
  326.         InsertMenu(theGlobals.normalPopupMenu.hMenu, -1L);
  327.         CalcMenuSize(theGlobals.normalPopupMenu.hMenu);
  328.         theGlobals.normalPopupMenu.selectedItem = 1;
  329.         theGlobals.normalPopupMenu.smallFont = FALSE;
  330.         GetDialogItem(theDialog, popup1Item, &iType, &iHandle, &iRect);
  331.         SetDialogItem(theDialog, popup1Item, userItem, (Handle) NewUserItemProc(UpdatePopUp), &iRect);
  332.         
  333.         theGlobals.smallPopupMenu.hMenu = GetMenu(smallPopupID);
  334.         InsertMenu(theGlobals.smallPopupMenu.hMenu, -1L);
  335.         CalcMenuSize(theGlobals.smallPopupMenu.hMenu);
  336.         theGlobals.smallPopupMenu.selectedItem = 1;
  337.         theGlobals.smallPopupMenu.smallFont = TRUE;
  338.         GetDialogItem(theDialog, popup2Item, &iType, &iHandle, &iRect);
  339.         SetDialogItem(theDialog, popup2Item, userItem, (Handle) NewUserItemProc(UpdatePopUp), &iRect);
  340.         
  341.         GetDialogItem(theDialog, defaultItem, &iType, &iHandle, &iRect);
  342.         SetDialogItem(theDialog, defaultItem, userItem, (Handle) NewUserItemProc(DrawDefaultButton), &iRect);
  343.  
  344.         //SetDItem(dlg, dDefault, kind, (Handle) ZoneListDraw, &r);
  345.  
  346. //GetDItem(CPDialog, editItem, &itemType, &itemHandle, &itemRect);        
  347.         ShowWindow(theDialog);
  348.         HandleEvents(theDialog);
  349.         
  350.         DeleteMenu(normalPopupID);
  351.         DeleteMenu(smallPopupID);
  352.  
  353.         DisposeDialog(theDialog);
  354.     }
  355. }
  356.  
  357.  
  358. long PopUpSelect (MenuHandle theMenu, Point popPt, short popupItem, Boolean useWFont)
  359. {
  360.     short       item;
  361.     short       itemMark;
  362.     short       oldSysFont, oldWMgrFont, oldCWMgrFont;
  363.     short       oldSysSize, oldWMgrSize, oldCWMgrSize;
  364.     GrafPtr     curPort, wMgrPort;
  365.     CGrafPtr    wMgrCPort;
  366.     SysEnvRec   theWorld;
  367.  
  368.     oldSysFont = LMGetSysFontFam();
  369.     oldSysSize = LMGetSysFontSize();
  370.  
  371.         /* check if we need to use window font */
  372.  
  373.     GetPort (&curPort);
  374.     if (curPort->txFont == oldSysFont && curPort->txSize == oldSysSize)
  375.         useWFont = false;        /* window font _is_ system font! */
  376.  
  377.     if (useWFont) {
  378.         /* hack to fix bugs caused by programs that mess up the WindowMgr port(s) */
  379.         /*  (e.g. MacWrite & Word)  - thanks to Leonard Rosenthal for soln */
  380.         GetWMgrPort (&wMgrPort);
  381.         SetPort (wMgrPort);
  382.         oldWMgrFont = wMgrPort->txFont;
  383.         oldWMgrSize = wMgrPort->txSize;
  384.         TextFont (systemFont);
  385.         TextSize (0);
  386.         
  387.         if (SysEnvirons (1, &theWorld) == noErr && theWorld.hasColorQD) {
  388.             GetCWMgrPort (&wMgrCPort);
  389.             SetPort ((GrafPtr)wMgrCPort);
  390.             oldCWMgrFont = wMgrCPort->txFont;
  391.             oldCWMgrSize = wMgrCPort->txSize;
  392.             TextFont (systemFont);
  393.             TextSize (0);
  394.             //TextFont (wMgrCPort->txFont);
  395.             //TextSize (wMgrCPort->txSize);
  396.             }
  397.         else
  398.             theWorld.hasColorQD = false;
  399.             
  400.             
  401.         SetPort (curPort);
  402.  
  403.         LMSetSysFontFam(curPort->txFont);
  404.         LMSetSysFontSize(curPort->txSize);
  405.         LMSetLastSPExtra(-1L);
  406.         
  407.         }
  408.  
  409.     if (popupItem > 0) {            /* save old mark and check item */
  410.         GetItemMark (theMenu, popupItem, &itemMark);
  411.         SetItemMark (theMenu, popupItem, useWFont? '*' : checkMark);
  412.         }
  413.         
  414.     item = PopUpMenuSelect (theMenu, popPt.v, popPt.h, (popupItem>0) ? popupItem : 1);
  415.  
  416.     if (popupItem > 0)                /* restore old item mark */
  417.         SetItemMark (theMenu, popupItem, itemMark);
  418.  
  419.     if (useWFont) {
  420.         SetPort (wMgrPort);
  421.         TextFont (oldWMgrFont);
  422.         TextSize (oldWMgrSize);
  423.         if (theWorld.hasColorQD) {
  424.             SetPort ((GrafPtr)wMgrCPort);
  425.             TextFont (oldCWMgrFont);
  426.             TextSize (oldCWMgrSize);
  427.             }
  428.         SetPort(curPort);
  429.  
  430.         LMSetSysFontSize(oldSysSize);
  431.         LMSetSysFontFam(oldSysFont);
  432.         LMSetLastSPExtra(-1L);
  433.         }
  434.  
  435.     return item;
  436. }
  437.  
  438.  
  439. /*
  440.                         GetPort(&savePort);
  441.                         GetWMgrPort(&wmPort);
  442.                         GetCWMgrPort(&wmCPort);
  443.  
  444.                         saveFont = wmPort->txFont;
  445.                         saveSize = wmPort->txSize;
  446.                         saveFace = wmPort->txFace;
  447.  
  448.                         saveCFont = wmCPort->txFont;
  449.                         saveCSize = wmCPort->txSize;
  450.                         saveCFace = wmCPort->txFace;
  451.  
  452.                         SetPort(wmPort);
  453.                         TextFont(applFont);
  454.                         TextSize(9);
  455.                         TextFace(0);
  456.  
  457.                         SetPort((GrafPtr)wmCPort);
  458.                         TextFont(applFont);
  459.                         TextSize(9);
  460.                         TextFace(0);
  461.                         SetPort(savePort);
  462.  
  463.                         sysFontSize = LMGetSysFontSize();
  464.                         LMSetSysFontSize(9);
  465.  
  466.                         sysFontFamily = LMGetSysFontFam();
  467.                         LMSetSysFontFam(applFont);
  468.  
  469.                         LMSetCurFMFam(-1);
  470.  
  471. Then after popupmenuselect, I set everything back to how it was before:
  472.                         LMSetSysFontSize(sysFontSize);
  473.                         LMSetSysFontFam(sysFontFamily);
  474.                         LMSetCurFMFam(-1);
  475.  
  476.                         SetPort(wmPort);
  477.                         TextFont(saveFont);
  478.                         TextSize(saveSize);
  479.                         TextFace(saveFace);
  480.  
  481.                         SetPort((GrafPtr)wmCPort);
  482.                         TextFont(saveCFont);
  483.                         TextSize(saveCSize);
  484.                         TextFace(saveCFace);
  485.  
  486.                         SetPort(savePort);
  487.  
  488. */
  489.